﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using blacksoft.Models;
using blacksoft.Constantes;

namespace blacksoft.Controllers
{
    public class UnidadTransporteController : Controller
    {
        private inf245travelbusEntities db = new inf245travelbusEntities();

        //Declaración de constantes internas
        //Estados posibles
        private class Estado
        {
            public string valor { get; set; }
            public string nombre { get; set; }

            public Estado(string valor, string nombre)
            {
                this.valor = valor;
                this.nombre = nombre;
            }
        }
        private List<Estado> estados = new List<Estado> { new Estado("AC", "Activo"), new Estado("IN", "Inactivo") };
        private List<Estado> estados_full = new List<Estado> { new Estado("AC", "Activo"), new Estado("IN", "Inactivo"), new Estado("AN", "Anulado") };
        //Cadena para anulación de unidades
        private Estado est_anulado = new Estado("AN", "Anulado");
        //Tipos de serivicio posibles
        private class Servicio
        {
            public int valor { get; set; }
            public string nombre { get; set; }

            public Servicio(int valor, string nombre)
            {
                this.valor = valor;
                this.nombre = nombre;
            }
        }
        private List<Servicio> tipos_servicio = new List<Servicio> { new Servicio(1, "Económico"), new Servicio(2, "VIP") };
        //Tipos de estado posibles para RutaxBus
        private string[] estados_ruta_bus = { "AC", "IN" };
        //Controlador para Ruta_x_UnidadTransporte
        Ruta_x_UnidadTransporteController ruta_unidad_controller = new Ruta_x_UnidadTransporteController();

        private class ItemListaRutas
        {
            public int id_ruta { get; set; }
            public string nombre { get; set; }

            public ItemListaRutas(int id_ruta, string nombre)
            {
                this.id_ruta = id_ruta;
                this.nombre = nombre;
            }
        }
        private List<ItemListaRutas> obtenerListRutas()
        {
            var ruta_qry = from r in db.Ruta
                           select r;
            string activo = estados[0].valor;
            ruta_qry = ruta_qry.Where(r => r.Estado == activo);
            List<ItemListaRutas> ruta_lst = new List<ItemListaRutas>();
            foreach (var ruta in ruta_qry)
            {
                ruta_lst.Add(new ItemListaRutas(ruta.IDRuta, ruta.Origen + " - " + ruta.Destino));
            }
            return ruta_lst;
        }

        // GET: /UnidadTransporte/
        public ActionResult Index(string search_placa, string search_año, string search_motor, string search_tipo, string search_estado, string search_terminal)
        {
            ActionResult result_seguridad = ValidarSeguridad();
            if (result_seguridad!= null)
            {
                return result_seguridad;
            }
            bool global = PerfilsController.TienePermiso((int)Session["Permisos"], PerfilsController.GLOBAL);
            ViewBag.Global = global;

            var unidades = from u in db.UnidadTransporte
                           select u;
            //Si no es global
            if (!PerfilsController.TienePermiso((int)Session["Permisos"], PerfilsController.GLOBAL))
            {
                //Select de todas las unidades de la terminal
                int id_terminal = (int)Session["IDTerminal"];
                unidades = unidades.Where(u => u.IDTerminal == id_terminal);
            }

            if (!String.IsNullOrEmpty(search_placa))
            {
                unidades = unidades.Where(s => s.NumeroPlaca.Contains(search_placa));
            }

            //Construcción de lista de años existentes para el filtro
            var año_lst = new List<int?>();
            var año_qry = from u in db.UnidadTransporte
                          orderby u.AñoFabricacion
                          select u.AñoFabricacion;
            año_lst.AddRange(año_qry.Distinct());
            ViewBag.search_año = new SelectList(año_lst);

            if (!string.IsNullOrEmpty(search_año))
            {
                int año = int.Parse(search_año);
                unidades = unidades.Where(s => s.AñoFabricacion == año);
            }

            //Motor
            if (!string.IsNullOrEmpty(search_motor))
            {
                unidades = unidades.Where(s => s.NombreMotor.Contains(search_motor));
            }

            //Construcción de lista de tipos
            ViewBag.search_tipo = new SelectList(tipos_servicio, "valor", "nombre");


            if (!string.IsNullOrEmpty(search_tipo))
            {
                int tipo = int.Parse(search_tipo);
                unidades = unidades.Where(s => s.TipoServicio == tipo); //search_tipo
            }

            //Construcción de lista de estados
            ViewBag.search_estado = new SelectList(estados_full, "valor", "nombre");
            ViewBag.EstadoAC = estados_full.Find(e => e.valor == "AC").nombre;
            ViewBag.EstadoIN = estados_full.Find(e => e.valor == "IN").nombre;
            ViewBag.EstadoAN = estados_full.Find(e => e.valor == "AN").nombre;

            if (!string.IsNullOrEmpty(search_estado))
            {
                unidades = unidades.Where(s => s.Estado == search_estado);
            }

            //Construcción de lista de terminales existentes para el filtro
            var term_lst = new List<string>();
            var term_qry = from t in db.UnidadTransporte
                           orderby t.Terminal.Nombre
                           select t.Terminal.Nombre;
            term_lst.AddRange(term_qry.Distinct());
            ViewBag.search_terminal = new SelectList(term_lst);

            if (!string.IsNullOrEmpty(search_terminal))
            {
                unidades = unidades.Where(u => u.Terminal.Nombre == search_terminal);
            }

            //No mostrar anulados
            if (search_estado != est_anulado.valor)
            {
                unidades = unidades.Where(u => u.Estado != est_anulado.valor);
            }

            try
            {
                ViewBag.Tipo1 = tipos_servicio.ElementAt(0).nombre;
                ViewBag.Tipo2 = tipos_servicio.ElementAt(1).nombre;
            }
            catch
            {
                TempData["index_failure"] = "no se pudo encontrar los nombres de los tipos de servicio";
                return RedirectToAction("Index");
            }
            unidades = unidades.OrderBy(s => s.NumeroPlaca);
            return View(unidades);
        }

        // GET: /UnidadTransporte/Details/5
        public ActionResult Details(int? id)
        {
            ActionResult result_seguridad = ValidarSeguridad();
            if (result_seguridad != null)
            {
                return result_seguridad;
            }
            bool global = PerfilsController.TienePermiso((int)Session["Permisos"], PerfilsController.GLOBAL);
            ViewBag.Global = global;

            if (id == null)
            {
                return View("Error404");
            }
            UnidadTransporte unidadtransporte = db.UnidadTransporte.Find(id);
            if (unidadtransporte == null)
            {
                return View("Error404");
            }

            //No permitir acceso a info de otras terminales
            if (!global && unidadtransporte.IDTerminal != (int)Session["IDTerminal"])
            {
                TempData["SinPermiso"] = SystemField.SIN_PERMISO;
                return RedirectToAction("Index", "ModuloAdmin");
            }

            try
            {
                ViewBag.TipoServicio = tipos_servicio.ElementAt((int)unidadtransporte.TipoServicio - 1).nombre;
                ViewBag.Estado = estados.Find(e => e.valor == unidadtransporte.Estado).nombre;
            }
            catch
            {
                TempData["details_failure"] = "no se pudo encontrar los nombres de los tipos de servicio";
                return RedirectToAction("Index");
            }

            ViewBag.EstadoAC = estados_full.Find(e => e.valor == "AC").nombre;
            ViewBag.EstadoIN = estados_full.Find(e => e.valor == "IN").nombre;
            ViewBag.EstadoAN = estados_full.Find(e => e.valor == "AN").nombre;

            return View(unidadtransporte);
        }

        // GET: /UnidadTransporte/Create
        public ActionResult Create()
        {
            ActionResult result_seguridad = ValidarSeguridad();
            if (result_seguridad != null)
            {
                return result_seguridad;
            }
            bool global = PerfilsController.TienePermiso((int)Session["Permisos"], PerfilsController.GLOBAL);
            ViewBag.Global = global;

            SelectList tipo = new SelectList(tipos_servicio, "valor", "nombre");
            ViewBag.TipoServicio = tipo;
            SelectList estado = new SelectList(estados, "valor", "nombre", estados[0].valor);
            ViewBag.Estado = estado;
            if (!global)
            {
                //Usuario no global
                ViewBag.IDTerminal = (int)Session["IDTerminal"];
            }
            else
            {
                //Usuario global
                string activo = estados[0].valor;
                var terminales = from t in db.Terminal
                                 where t.Estado == activo
                                 select t;
                int id_terminal = (int)Session["IDTerminal"];
                ViewBag.IDTerminal = new SelectList(terminales, "IDTerminal", "Nombre", id_terminal);
            }
            ViewBag.Ruta = new SelectList(obtenerListRutas(), "id_ruta", "nombre");

            return View();
        }

        // POST: /UnidadTransporte/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "IDUnidadTransporte,NumeroPlaca,AñoFabricacion,NombreMotor,TipoServicio,Estado,IDTerminal")] UnidadTransporte unidadtransporte, string ruta)
        {
            ActionResult result_seguridad = ValidarSeguridad();
            if (result_seguridad != null)
            {
                return result_seguridad;
            }
            bool global = PerfilsController.TienePermiso((int)Session["Permisos"], PerfilsController.GLOBAL);
            ViewBag.Global = global;

            string activo = estados[0].valor;
            var placas_qry = from u in db.UnidadTransporte
                             where u.Estado == activo
                             select u.NumeroPlaca;
            string placa_tmp = unidadtransporte.NumeroPlaca;
            if (placas_qry.Contains(placa_tmp))
            {
                TempData["create_failure"] = "ya existe una unidad con placa " + unidadtransporte.NumeroPlaca;
            }
            else if (unidadtransporte.AñoFabricacion > DateTime.Now.Year)
            {
                TempData["create_failure"] = "año inválido";
            }
            else if (DateTime.Now.Year - unidadtransporte.AñoFabricacion > 20)
            {
                TempData["create_failure"] = "no se puede registrar un bus con más de 20 años de antiguedad";
            }
            else
            {
                if (ModelState.IsValid)
                {
                    db.UnidadTransporte.Add(unidadtransporte);
                    if (!string.IsNullOrEmpty(ruta))
                    {
                        int? id_ruta = int.Parse(ruta);
                        Ruta_x_UnidadTransporte ruta_bus = new Ruta_x_UnidadTransporte();
                        ruta_bus.IDUnidadTransporte = unidadtransporte.IDUnidadTransporte;
                        ruta_bus.IDRuta = id_ruta;
                        ruta_bus.Estado = estados_ruta_bus[0];
                        ruta_bus.Fecha = DateTime.Now;
                        db.Ruta_x_UnidadTransporte.Add(ruta_bus);
                    }
                    try
                    {
                        db.SaveChanges();
                    }
                    catch
                    {
                        TempData["create_failure"] = "la unidad no se pudo registrar";
                        return RedirectToAction("Index");
                    }

                    TempData["create_success"] = "la unidad se registró exitosamente";
                    return RedirectToAction("Index");
                }
            }

            SelectList tipo = new SelectList(tipos_servicio, "valor", "nombre", unidadtransporte.TipoServicio);
            ViewBag.TipoServicio = tipo;
            SelectList estado = new SelectList(estados, "valor", "nombre", unidadtransporte.Estado);
            ViewBag.Estado = estado;
            if (!global)
            {
                //Usuario no global
                ViewBag.IDTerminal = (int)Session["IDTerminal"];
            }
            else
            {
                //Usuario global
                var terminales = from t in db.Terminal
                                 where t.Estado == activo
                                 select t;
                int id_terminal = (int)Session["IDTerminal"];
                ViewBag.IDTerminal = new SelectList(terminales, "IDTerminal", "Nombre", id_terminal);
            }
            ViewBag.Ruta = new SelectList(obtenerListRutas(), "id_ruta", "nombre");

            return View(unidadtransporte);
        }

        // GET: /UnidadTransporte/Edit/5
        public ActionResult Edit(int? id)
        {
            ActionResult result_seguridad = ValidarSeguridad();
            if (result_seguridad != null)
            {
                return result_seguridad;
            }
            bool global = PerfilsController.TienePermiso((int)Session["Permisos"], PerfilsController.GLOBAL);
            ViewBag.Global = global;

            if (id == null)
            {
                return View("Error404");
            }
            try
            {
                UnidadTransporte unidadtransporte = db.UnidadTransporte.Find(id);
                if (unidadtransporte == null)
                {
                    return View("Error404");
                }
                //No permitir acceso a info de otras terminales
                if (!global && unidadtransporte.IDTerminal != (int)Session["IDTerminal"])
                {
                    TempData["SinPermiso"] = SystemField.SIN_PERMISO;
                    return RedirectToAction("Index", "ModuloAdmin");
                }

                List<ItemListaRutas> rutas = obtenerListRutas();
                if (unidadtransporte.Ruta_x_UnidadTransporte != null && unidadtransporte.Ruta_x_UnidadTransporte.Count() != 0)
                {
                    if (unidadtransporte.Ruta_x_UnidadTransporte.Where(r => r.Estado == estados_ruta_bus[0]).Count() == 1)
                    {
                        int? id_ruta = unidadtransporte.Ruta_x_UnidadTransporte.Where(r => r.Estado == estados_ruta_bus[0]).Single().IDRuta;
                        try
                        {
                            Ruta actual = db.Ruta.Find(id_ruta);
                            ItemListaRutas actualItem = new ItemListaRutas(actual.IDRuta, actual.Origen + " - " + actual.Destino);
                            ViewBag.Ruta = new SelectList(rutas, "id_ruta", "nombre", actualItem.id_ruta);
                        }
                        catch
                        {
                            TempData["edit_failure"] = "no se encontró una ruta de la unidad";
                            return RedirectToAction("Index");
                        }
                    }
                    else
                        ViewBag.Ruta = new SelectList(rutas, "id_ruta", "nombre");
                }
                else
                    ViewBag.Ruta = new SelectList(rutas, "id_ruta", "nombre");
                SelectList tipo = new SelectList(tipos_servicio, "valor", "nombre", unidadtransporte.TipoServicio);
                ViewBag.TipoServicio = tipo;
                SelectList estado = new SelectList(estados, "valor", "nombre", unidadtransporte.Estado);
                ViewBag.Estado = estado;
                ViewBag.IDTerminal = new SelectList(db.Terminal, "IDTerminal", "Nombre", unidadtransporte.IDTerminal);
                return View(unidadtransporte);
            }
            catch
            {
                TempData["edit_failure"] = "no se encontró la unidad";
                return RedirectToAction("Index");
            }
        }

        // POST: /UnidadTransporte/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "IDUnidadTransporte,NumeroPlaca,AñoFabricacion,NombreMotor,TipoServicio,Estado,IDTerminal")] UnidadTransporte unidadtransporte, string Ruta)
        {
            ActionResult result_seguridad = ValidarSeguridad();
            if (result_seguridad != null)
            {
                return result_seguridad;
            }
            bool global = PerfilsController.TienePermiso((int)Session["Permisos"], PerfilsController.GLOBAL);
            ViewBag.Global = global;

            if (ModelState.IsValid)
            {
                db.Entry(unidadtransporte).State = EntityState.Modified;
                if (!string.IsNullOrEmpty(Ruta))
                {
                    int? id_ruta = int.Parse(Ruta); 
                    var ruta_unidad_qry = from rb in db.Ruta_x_UnidadTransporte
                                          select rb;
                    ruta_unidad_qry = ruta_unidad_qry.Where(rb => rb.IDUnidadTransporte == unidadtransporte.IDUnidadTransporte);
                    var ruta_unidad_subqry = ruta_unidad_qry.Where(rb => rb.IDRuta == id_ruta);
                    //Poner las rutas anteriores como inactivas
                    foreach (var item in ruta_unidad_qry)
                    {
                        Ruta_x_UnidadTransporte ruta_unidad = db.Ruta_x_UnidadTransporte.Find(item.IdRuta_x_UnidadTransporte);
                        if (item.IDRuta != id_ruta)
                        {
                            ruta_unidad.Estado = estados_ruta_bus[1];
                        }
                        else
                        {
                            ruta_unidad.Fecha = DateTime.Now;
                            ruta_unidad.Estado = estados_ruta_bus[0];
                        }
                        db.Entry(ruta_unidad).State = EntityState.Modified;
                    }
                    if (ruta_unidad_subqry.Count() == 0)
                    {
                        //Si nunca se ha asignado esta ruta a este bus
                        Ruta_x_UnidadTransporte ruta_bus = new Ruta_x_UnidadTransporte();
                        ruta_bus.IDUnidadTransporte = unidadtransporte.IDUnidadTransporte;
                        ruta_bus.IDRuta = id_ruta;
                        ruta_bus.Estado = estados_ruta_bus[0];
                        ruta_bus.Fecha = DateTime.Now;
                        db.Ruta_x_UnidadTransporte.Add(ruta_bus);
                    }
                }
                try
                {
                    db.SaveChanges();
                }
                catch
                {
                    TempData["edit_failure"] = "la unidad no se pudo modificar";
                    return RedirectToAction("Index");
                }
                TempData["edit_success"] = "unidad modificada exitosamente";
                return RedirectToAction("Index");
            }

            List<ItemListaRutas> rutas = obtenerListRutas(); ;
            ViewBag.Ruta = new SelectList(rutas, "id_ruta", "nombre");
            SelectList tipo = new SelectList(tipos_servicio, "valor", "nombre", unidadtransporte.TipoServicio);
            ViewBag.TipoServicio = tipo;
            SelectList estado = new SelectList(estados, "valor", "nombre", unidadtransporte.Estado);
            ViewBag.Estado = estado;
            ViewBag.IDTerminal = new SelectList(db.Terminal, "IDTerminal", "Nombre", unidadtransporte.IDTerminal);
            return View(unidadtransporte);
        }

        // GET: /UnidadTransporte/Delete/5
        public ActionResult Delete(int? id)
        {
            ActionResult result_seguridad = ValidarSeguridad();
            if (result_seguridad != null)
            {
                return result_seguridad;
            }
            bool global = PerfilsController.TienePermiso((int)Session["Permisos"], PerfilsController.GLOBAL);
            ViewBag.Global = global;

            if (id == null)
            {
                return View("Error404");
            }
            try
            {
                UnidadTransporte unidadtransporte = db.UnidadTransporte.Find(id);
                if (unidadtransporte == null)
                {
                    return View("Error404");
                }

                //No permitir acceso a info de otras terminales
                if (!global && unidadtransporte.IDTerminal != (int)Session["IDTerminal"])
                {
                    TempData["SinPermiso"] = SystemField.SIN_PERMISO;
                    return RedirectToAction("Index", "ModuloAdmin");
                }

                ViewBag.TipoServicio = tipos_servicio.ElementAt((int)unidadtransporte.TipoServicio - 1).nombre;
                ViewBag.Estado = estados.Find(e => e.valor == unidadtransporte.Estado).nombre;
                ViewBag.EstadoAC = estados_full.Find(e => e.valor == "AC").nombre;
                ViewBag.EstadoIN = estados_full.Find(e => e.valor == "IN").nombre;
                ViewBag.EstadoAN = estados_full.Find(e => e.valor == "AN").nombre;

                return View(unidadtransporte);
            }
            catch
            {
                TempData["delete_failure"] = "no se encontró la unidad";
                return RedirectToAction("Index");
            }
        }

        // POST: /UnidadTransporte/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            ActionResult result_seguridad = ValidarSeguridad();
            if (result_seguridad != null)
            {
                return result_seguridad;
            }
            bool global = PerfilsController.TienePermiso((int)Session["Permisos"], PerfilsController.GLOBAL);
            ViewBag.Global = global;

            UnidadTransporte unidadtransporte = db.UnidadTransporte.Find(id);
            if (ModelState.IsValid)
            {
                unidadtransporte.Estado = est_anulado.valor;
                db.Entry(unidadtransporte).State = EntityState.Modified;
                //db.UnidadTransporte.Remove(unidadtransporte);
                try
                {
                    db.SaveChanges();
                }
                catch
                {
                    TempData["delete_failure"] = "la unidad no se pudo eliminar";
                    return RedirectToAction("Index");
                }
            }


            TempData["delete_success"] = "la unidad se eliminó exitosamente";
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
        private ActionResult ValidarSeguridad()
        {

            if (Session["Permisos"] == null)
            {
                TempData["LogueatePrimero"] = SystemField.NO_LOGUEADO;
                return RedirectToAction("Index", "ValidarLogin");
            }
            //ESTOY LOGUEADO PERO NO TENGO PERMISO PARA REALIZAR ESTA ACCION
            if (!PerfilsController.TienePermiso((int)Session["Permisos"], PerfilsController.ADMINISTRACION))
            {
                TempData["SinPermiso"] = SystemField.SIN_PERMISO;
                return RedirectToAction("Index", "MainPageEmployes");
            }
            return null;
        }
    }
}
